This notebook uses code snippets and explanation from this course
The last type of container we will introduce in this topic is dictionaries. Programming is mostly about solving real-world problems as efficiently as possible, but it is also important to write and organize code in a human readable fashion. A dictionary offers a kind of abstraction that comes in handy a lot of times: it is a type of "associative memory" or key:value storage. It allows you to describe two pieces of data and their relationship.
At the end of this chapter, you will:
If you want to learn more about these topics, you might find the following links useful:
If you have questions about this chapter, please refer to the forum on Canvas.
In [ ]:
student_grades = ['Frank', 8, 'Susan', 7, 'Guido', 10]
In [ ]:
student = 'Frank'
index_of_student = student_grades.index(student) # we use the index method (list.index)
print('grade of', student, 'is', student_grades[index_of_student + 1])
However, you're not happy about the solution. Every time you request a grade, we need to first determine the position of the student in the list and then use that index + 1 to obtain the grade. That's pretty inefficient. The take home message here is that lists are not really good if we want two pieces of information together. Dictionaries for the rescue!
In [ ]:
student_grades = {'Frank': 8, 'Susan': 7, 'Guido': 10}
In [ ]:
student_grades['Frank']
In [ ]:
student_grades = {'Frank': 8, 'Susan': 7, 'Guido': 10}
Please note that keys in a dictionary have to immutable.
This works (strings as keys)
In [ ]:
student_grades = {'Frank': 8, 'Susan': 7, 'Guido': 10}
This does not (list as keys)
In [ ]:
a_dict = {['a', 'list']: 8}
Please note that the values in a dictionary can by any python object
This works (integers as values)
In [ ]:
a_dict = {'Frank': 8, 'Susan': 7}
But this as well (lists as values)
In [ ]:
another_dict = {'Frank' : [8], 'Susan' : [7]}
Please note that a dictionary can be empty (use dict()):
In [ ]:
an_empty_dict = dict()
another_empty_dict = {} # This works too, but it is less readable and confusing (looks similar to sets)
print(type(another_empty_dict), type(an_empty_dict))
In [ ]:
a_dict = dict()
print(a_dict)
In [ ]:
a_dict['Frank'] = 8
print(a_dict)
Please note that dictionary keys should be unique identifiers for the values in the dictionary. Key:value pairs get overwritten if you assign a different value to an existing key.
In [ ]:
a_dict = dict()
a_dict['Frank'] = 8
print(a_dict)
a_dict['Frank'] = 7
print(a_dict)
a_dict['Frank'] = 9
print(a_dict)
The most basic operation on a dictionary is a look-up. Simply enter the key and the dictionary returns the value.
In [ ]:
student_grades = {'Frank': 8, 'Susan': 7, 'Guido': 10}
In [ ]:
print(student_grades['Frank'])
If the key is not in the dictionary, it will return a KeyError.
In [ ]:
student_grades['Piet']
In order to avoid getting an error, you can use an if-statement
In [ ]:
key = 'Piet'
if key in student_grades:
print(student_grades[key])
else:
print(key, 'not in dictionary')
In [ ]:
key = 'Frank'
if key in student_grades:
print(student_grades[key])
else:
print(key, 'not in dictionary')
the keys method returns the keys in a dictionary
In [ ]:
student_grades = {'Frank': 8, 'Susan': 7, 'Guido': 10}
In [ ]:
the_keys = student_grades.keys()
print(the_keys)
the values method returns the values in a dictionary
In [ ]:
the_values = student_grades.values()
print(the_values)
We can use the built-in functions to inspect the keys and values. For example:
In [ ]:
the_values = student_grades.values()
print(len(the_values)) # number of values in a dict
print(max(the_values)) # highest value of values in a dict
print(min(the_values)) # lowest value of values in a dict
print(sum(the_values)) # sum of all values of values in a dict
However, what if we want to know which students got a 8 or higher? The items method is very useful for this scenario. Please carefully look at the following code snippet.
In [ ]:
student_grades = {'Frank': 8, 'Susan': 7, 'Guido': 10}
print(student_grades.items())
The items method returns a list of tuples. We can combine what we have learnt about looping and tuples to access the keys (the students' names) and values (their grades):
In [ ]:
for key, value in student_grades.items(): # please note the tuple unpacking
print(key, value)
This also makes it possible to detect which students obtained a grade of 8 or higher.
In [ ]:
for student, grade in student_grades.items():
if grade > 7:
print(student, grade)
In [ ]:
letter2freq = dict()
word = 'hippo'
for letter in word:
if letter in letter2freq: # add 1 to the dictionary if the keys exists
letter2freq[letter] += 1 # note: x +=1 does the same as x = x + 1
else:
letter2freq[letter] = 1 # set default value to 1 if key does not exists
print(letter, letter2freq)
print()
print(letter2freq)
You can do this as well with lists
In [ ]:
a_sentence = ['Obama', 'was', 'the', 'president', 'of', 'the', 'USA']
word2freq = dict()
for word in a_sentence:
if word in word2freq: # add 1 to the dictionary if the keys exists
word2freq[word] += 1
else:
word2freq[word] = 1 # set default value to 1 if key does not exists
print(word, word2freq)
print()
print(word2freq)
Python actually has a module, which is very useful for counting. It's called collections.
In [ ]:
from collections import Counter
In [ ]:
word_freq = Counter(['Obama', 'was', 'the', 'president', 'of', 'the', 'USA'])
print(word_freq)
Feel free to start using this module after the assignment of this block.
In [ ]:
a_nested_dictionary = {'a_key':
{'nested_key1': 1,
'nested_key2': 2,
'nested_key3': 3}
}
print(a_nested_dictionary)
Please note that the value is in fact a dictionary:
In [ ]:
print(a_nested_dictionary['a_key'])
In order to access the nested value, we must do a look up for each key on each nested level
In [ ]:
the_nested_value = a_nested_dictionary['a_key']['nested_key1']
print(the_nested_value)
Practice questions:
What do sets and dictionaries have in common?
What do lists and tuples have in common?
Can you add things to a list?
Can you add things to a tuples?
An overview:
property | set | list | tuple | dict keys | dict values |
---|---|---|---|---|---|
mutable (can you add add/remove?) | yes | yes | no | yes | yes |
can contain duplicates | no | yes | yes | no | yes |
ordered | no | yes | yes | yes, but do not rely on it | depends on type of value |
finding element(s) | quick | slow | slow | quick | depends on type of value |
can contain | immutables | all | all | immutable | all |
In [ ]:
# your code here
In [ ]:
# your code here
In [ ]:
# you code here
In [ ]: